package cn.edu.xmu.oomall.comment.dao;


import cn.edu.xmu.javaee.core.exception.BusinessException;
import cn.edu.xmu.javaee.core.mapper.RedisUtil;
import cn.edu.xmu.javaee.core.model.ReturnNo;
import cn.edu.xmu.javaee.core.model.dto.UserDto;
import cn.edu.xmu.javaee.core.util.CloneFactory;
import cn.edu.xmu.oomall.comment.dao.bo.Comment;
import cn.edu.xmu.oomall.comment.mapper.CommentPoMapper;
import cn.edu.xmu.oomall.comment.mapper.po.CommentPo;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Repository
@RefreshScope
@RequiredArgsConstructor
public class CommentDao {

    private final static Logger logger = LoggerFactory.getLogger(CommentDao.class);

    private static final String KEY = "C%d";

    private final CommentPoMapper commentPoMapper;

    @Value("${oomall.comment.shop-logistics.timeout}")
    private int timeout;

    private final RedisUtil redisUtil;

    public void build(Comment bo) {
        bo.setCommentDao(this);
    }

    public Comment build(CommentPo po, Optional<String> redisKey) {
        Comment bo = CloneFactory.copy(new Comment(), po);
        this.build(bo);
        redisKey.ifPresent(key -> redisUtil.set(key, bo, timeout));
        return bo;
    }

    /**
     * 查找评论
     *
     * @param id 评论id
     * @return 评论
     * @throws RuntimeException 评论不存在
     */
    public Comment findById(Long id) throws RuntimeException {
        logger.debug("findById: id = {}", id);
        assert (!Objects.isNull(id)) : "id can not be null";

        String key = String.format(KEY, id);
        Comment bo = (Comment) redisUtil.get(key);

        if (Objects.isNull(bo)) {
            // 缓存中没有
            Optional<CommentPo> ret = commentPoMapper.findById(id);
            if (ret.isPresent()) {
                logger.debug("findById: retrieve from database comment = {}", ret.get());
                return this.build(ret.get(), Optional.of(key));
            } else {
                throw new BusinessException(ReturnNo.RESOURCE_ID_NOTEXIST,
                        String.format(ReturnNo.RESOURCE_ID_NOTEXIST.getMessage(), "评论", id));
            }
        } else {
            logger.debug("findById: hit in redis key = {}, comment = {}", key, bo);
            this.build(bo);
            return bo;
        }
    }

    /**
     * 创建评论
     *
     * @param bo   评论bo
     * @param user 登录用户
     */
    public Comment insert(Comment bo, UserDto user) throws RuntimeException {
        bo.setCreator(user);
        bo.setGmtCreate(LocalDateTime.now());
        CommentPo po = CloneFactory.copy(new CommentPo(), bo);
        logger.debug("save: po = {}", po);
        po = commentPoMapper.save(po);
        bo.setId(po.getId());
        return bo;
    }

    /**
     * 修改评论状态
     *
     * @param bo   评论业务对象
     * @param user 操作用户
     */
    public void save(Comment bo, UserDto user) throws RuntimeException {
        bo.setModifier(user);
        bo.setGmtModified(LocalDateTime.now());

        // 2. 业务对象转换为持久化对象
        CommentPo po = CloneFactory.copy(new CommentPo(), bo);
        logger.debug("save: po = {}", po);

        commentPoMapper.save(po);
    }

    public List<CommentPo> findByPid(Long id) {
        return commentPoMapper.findByPid(id);
    }
}
